/**
 * Author: ling
 * Create Time: 2018-12-04 11:00
 * Description: 组合模式
 */

/**
 * 1. 组合模式不是父子关系
 * 2. 对叶对象操作的一致性
 * 3. 双向映射关系
 * 4. 用职责链模式提高组合模式的性能
 *
 * 使用场景：
 * 1. 表示对象的部分-整体层次结构
 * 2. 客户希望统一对待树中的所有对象
 *
 * 系统中的每个对象看起来都与其他对象差不多。
 * 它们的区别只有在运行的时候会才会显现出来，这会使代码难以理解。
 * 此外，如果通过组合模式创建了太多的对象，那么这些对象可能会让系统负担不起。
 */

Folder = function (name) {
  this.name = name;
  this.parent = null;
  this.files = [];
};
Folder.prototype.add = function (file) {
  file.parent = this;
  this.files.push(file)
};
Folder.prototype.scan = function () {
  console.log('start scan: ' + this.name);
  for (let file of this.files) {
    file.scan();
  }
};
Folder.prototype.remove = function () {
  // 根节点或树外的游离节点
  if(!this.parent) {
    return ;
  }

  for(let files = this.parent.files, i = files.length - 1; i >= 0; i--) {
    if(files[i] === this) {
      files.splice(i, 1)
    }
  }
};

File = function (name) {
  this.name = name;
  this.parent = null;
};
File.prototype.add = function () {
  throw new Error('不能添加在文件下面')
};
File.prototype.scan = function () {
  console.log('start scan：', this.name)
};
File.prototype.remove = function () {
  if(!this.parent) {
    return ;
  }

  for(let files = this.parent.files, i = files.length - 1; i >= 0; i--) {
    if(files[i] === this) {
      files.splice(i, 1)
    }
  }
};

folder = new Folder('学习资料');
folder1 = new Folder('JavaScript');

file1 = new Folder('深入浅出Node.js');

folder1.add(new File('JavaScript设计模式'));
folder.add(folder1);
folder.add(file1);

folder1.remove();
folder.scan();
